package br.edu.ufpel.cgic.main;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Random;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.export.JRCsvExporter;
import net.sf.jasperreports.engine.export.JRCsvExporterParameter;
import net.sf.jasperreports.engine.export.JRXlsExporter;
import net.sf.jasperreports.engine.export.oasis.JROdsExporter;
import net.sf.jasperreports.engine.export.oasis.JROdtExporter;

import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

public class Main {

	private static JasperPrint report;
	private static Properties properties = null;

	public static void main(String[] args) {		
		try {
			File file = new File(args[3]);
			properties = new Properties();
			FileInputStream fis = null;
			fis = new FileInputStream(file);
			properties.load(fis);
			fis.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

		new Main().generateReport(args[0], args[1], args[2]);
	}

	public void generateReport(String nameReportJasper, String params, String format) {
		Random random = new Random();
		String generatedNameReport = String.valueOf(random.nextLong()).replaceAll("-", String.valueOf(random.nextInt(10)));
		Map<String, Object> parameters = setParameters(params, nameReportJasper);
		String database = parameters.get("DATABASE").toString();

		try {
			report = JasperFillManager.fillReport(nameReportJasper, parameters, getConnectionDataBase(database));
		} catch (JRException e) {
			e.printStackTrace();
		}
		
		try {
			switch (Integer.parseInt(format)) {
				case 1:			
					System.out.println(generatePDF(report, generatedNameReport));			
					break;
				case 2:
					System.out.println(generateHTML(report, generatedNameReport));
					break;
				case 3:
					System.out.println(generateXML(report, generatedNameReport));
					break;
				case 4:
					System.out.println(generateXLS(report, generatedNameReport));
					break;
				case 5:
					System.out.println(generateCSV(report, generatedNameReport));
					break;
				case 6:
					System.out.println(generateODT(report, generatedNameReport));
					break;
				case 7:
					System.out.println(generateODS(report, generatedNameReport));
					break;
			}
		} catch (JRException e) {
			e.printStackTrace();
		}
	}

	public String generatePDF(JasperPrint report, String nameReport) throws JRException {
		JasperExportManager.exportReportToPdfFile(report, properties.getProperty("jasper.path_destination") + nameReport + ".pdf");
		return nameReport + ".pdf";
	}
	
	public String generateHTML(JasperPrint report, String nameReport) throws JRException {
		JasperExportManager.exportReportToHtmlFile(report, properties.getProperty("jasper.path_destination") + nameReport + ".html");
		return nameReport + ".html";
	}
	
	public String generateXML(JasperPrint report, String nameReport) throws JRException {
		JasperExportManager.exportReportToXmlFile(report, properties.getProperty("jasper.path_destination") + nameReport + ".xml", true);
		return nameReport + ".xml";
	}
	
	public String generateXLS(JasperPrint report, String nameReport) throws JRException {
		JRXlsExporter exportXLS = new JRXlsExporter();
		exportXLS.setParameter(JRExporterParameter.JASPER_PRINT, report);
		exportXLS.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, properties.getProperty("jasper.path_destination") + nameReport + ".xls");
		exportXLS.setParameter(JRExporterParameter.IGNORE_PAGE_MARGINS, Boolean.TRUE);
		exportXLS.setParameter(JRExporterParameter.CHARACTER_ENCODING, "UTF-8");
		exportXLS.exportReport();
		return nameReport + ".xls";
	}
	
	public String generateCSV(JasperPrint report, String nameReport) throws JRException {
		JRCsvExporter exportCSV = new JRCsvExporter();
		exportCSV.setParameter(JRCsvExporterParameter.JASPER_PRINT, report);
		exportCSV.setParameter(JRCsvExporterParameter.FIELD_DELIMITER, "|");
		exportCSV.setParameter(JRCsvExporterParameter.RECORD_DELIMITER, "\n");
		exportCSV.setParameter(JRCsvExporterParameter.OUTPUT_FILE_NAME, properties.getProperty("jasper.path_destination") + nameReport + ".csv");
		exportCSV.setParameter(JRCsvExporterParameter.CHARACTER_ENCODING, "UTF-8");
		exportCSV.exportReport();
		return nameReport + ".csv";
	}
	
	public String generateODT(JasperPrint report, String nameReport) throws JRException {
		JROdtExporter exportODT = new JROdtExporter();
		exportODT.setParameter(JRExporterParameter.JASPER_PRINT, report);
		exportODT.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, properties.getProperty("jasper.path_destination") + nameReport + ".odt");
		exportODT.setParameter(JRExporterParameter.OFFSET_X, new Integer(0));
		exportODT.setParameter(JRExporterParameter.OFFSET_Y, new Integer(0));
		exportODT.setParameter(JRExporterParameter.CHARACTER_ENCODING, "UTF-8");
		exportODT.exportReport();
		return nameReport + ".odt";
	}
	
	public String generateODS(JasperPrint report, String nameReport) throws JRException {
		JROdsExporter exportODS = new JROdsExporter();
		exportODS.setParameter(JRExporterParameter.JASPER_PRINT, report);
		exportODS.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, properties.getProperty("jasper.path_destination") + nameReport + ".ods");
		exportODS.exportReport();
		return nameReport + ".ods";
	}
	
	private Connection getConnectionDataBase(String database) {
		Connection connection = null;
		try {
			if (properties.getProperty(database+".dbdriver").equals("postgres")) {
				Class.forName("org.postgresql.Driver");
				connection = DriverManager.getConnection("jdbc:postgresql://" + properties.getProperty(database+".host").trim() + ":" + properties.getProperty(database+".port").trim() + "/" + properties.getProperty(database+".dbname").trim(), properties.getProperty(database+".username").trim(), properties.getProperty(database+".password").trim());
			} else if (properties.getProperty(database+".dbdriver").equals("mysql")) {
				Class.forName("com.mysql.jdbc.Driver");
		        connection = DriverManager.getConnection("jdbc:mysql://" + properties.getProperty(database+".host").trim() + ":" + properties.getProperty(database+".port").trim() + "/" + properties.getProperty(database+".dbname").trim(), properties.getProperty(database+".username").trim(), properties.getProperty(database+".password").trim());
			} else if (properties.getProperty(database+".dbdriver").equals("db2")) {
				Class.forName("com.ibm.db2.jcc.DB2Driver");
		        connection = DriverManager.getConnection("jdbc:db2://" + properties.getProperty(database+".host").trim() + ":" + properties.getProperty(database+".port").trim() + "/" + properties.getProperty(database+".dbname").trim(), properties.getProperty(database+".username").trim(), properties.getProperty(database+".password").trim());
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}     
		return connection;
	}
	
	private Map<String, Object> setParameters(String params, String nameReportJasper) {
		String[] nameReport = nameReportJasper.split("/");
		Map<String, Object> parameters = new HashMap<String, Object>();
		parameters.put("IMG_REPORT_1", properties.getProperty("jasper.img_report_1"));
		parameters.put("IMG_REPORT_2", properties.getProperty("jasper.img_report_2"));		
		parameters.put("IMG_REPORT_3", properties.getProperty("jasper.img_report_3"));
		parameters.put("IMG_REPORT_4", properties.getProperty("jasper.img_report_4"));
		parameters.put("IMG_REPORT_5", properties.getProperty("jasper.img_report_5"));
		parameters.put("IMG_REPORT_6", properties.getProperty("jasper.img_report_6"));		
		parameters.put("IMG_REPORT_7", properties.getProperty("jasper.img_report_7"));
		parameters.put("IMG_REPORT_8", properties.getProperty("jasper.img_report_8"));
		parameters.put("IMG_REPORT_9", properties.getProperty("jasper.img_report_9"));
		parameters.put("IMG_REPORT_10", properties.getProperty("jasper.img_report_10"));
		parameters.put("COMPANY", properties.getProperty("jasper.company"));
		parameters.put("DEPARTMENT", properties.getProperty("jasper.department"));
		parameters.put("INSTITUICAO", properties.getProperty("jasper.instituicao"));
		parameters.put("SETOR", properties.getProperty("jasper.setor"));
		parameters.put("REPORT_LOCALE", new Locale("pt", "BR"));

		if(properties.getProperty("jasper.debug").equals("On"))
			parameters.put("NAME_REPORT_COMPILAD", nameReport[(nameReport.length - 3)] + "/"+ nameReport[(nameReport.length - 2)] + "/"+ nameReport[(nameReport.length - 1)]);
        else
            parameters.put("NAME_REPORT_COMPILAD", "");
		
		JSONObject obj = (JSONObject) JSONValue.parse(params);
		@SuppressWarnings("rawtypes")
		Iterator iter = obj.keySet().iterator();

		while (iter.hasNext()) {
			Object object = iter.next();
			parameters.put(object.toString(), this.replaceParam(obj.get(object).toString()));
		}
		return parameters;
	}
	
	private String replaceParam(String param){
		String search[] = {"!#", "#!"};
		String replace[] = {"<", ">"};		
		
		for (int i = 0; i < search.length; i++){
			param = param.replaceAll(search[i], replace[i]);			
		}

		return param;
	}

}